home *** CD-ROM | disk | FTP | other *** search
- #!/sbin/runscript
- # Copyright (c) 2004-2005 Gentoo Foundation
- # Distributed under the terms of the GNU General Public License v2
- # $Header$
-
- # Contributed by Roy Marples (uberlord@gentoo.org)
- # Many thanks to Aron Griffis (agriffis@gentoo.org)
- # for help, ideas and patches
-
- #NB: Config is in /etc/conf.d/net
-
- if [[ -n ${NET_DEBUG} ]]; then
- set -x
- devnull=/dev/stderr
- else
- devnull=/dev/null
- fi
-
- # For pcmcia users. note that pcmcia must be added to the same
- # runlevel as the net.* script that needs it.
- depend() {
- use coldplug hotplug pcmcia usb isdn wlan isapnp
-
- # Load any custom depend functions for the given interface
- # For example, br0 may need eth0 and eth1
- local iface=${myservice##*.}
- [[ $( type -t depend_${iface} ) == "function" ]] && depend_${iface}
- }
-
- # Define where our modules are
- MODULES_DIR=/lib/rcscripts/net.modules.d
-
- # Load some functions shared between ourselves and our dhcp helpers
- source ${MODULES_DIR}/helpers.d/functions
-
- # Make some wrappers to fudge after/before/need/use depend flags.
- # These are callbacks so mods[i] will be set.
- after() {
- local x="$*"
- [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
- eval "${MODULE}_after() { echo \"$x\"; }"
- }
- before() {
- local x="$*"
- [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
- eval "${MODULE}_before() { echo \"$x\"; }"
- }
- need() {
- local x="$*"
- [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
- eval "${MODULE}_need() { echo \"$x\"; }"
- }
- installed() {
- local x="$*"
- [[ $# -gt 1 ]] && x=$( echo -e "${x// /\n}" | sort | xargs )
- # We deliberately misspell this as _installed will probably be used
- # at some point
- eval "${MODULE}_instlled() { echo \"$x\"; }"
- }
-
- sort() {
- LC_ALL=C /bin/sort "$@"
- }
-
- # void module_class_wrap(char *module, char *provides)
- # Setup class wrappers: interface_up -> iproute2_up, for example
- module_class_wrap() {
- local module=${1} provides=${2} x
-
- # Don't wrap functions if another module already has
- [[ $( type -t ${provides}_provides ) == function ]] && return
-
- for x in $( typeset -f | grep -o ^${module}_'[^ ]*' ); do
- eval "${provides}${x#${module}}() { ${x} \"\$@\"; }"
- done
- }
-
- # bool module_load_minimum(char *module)
- #
- # Does the minimum checking on a module - even when forcing
- module_load_minimum() {
- local f=${1} MODULE=${1##*/}
-
- if [[ ! -f ${f} ]]; then
- eerror "${f} does not exist"
- return 1
- fi
-
- if ! source ${f} ; then
- eerror "${MODULE} failed a sanity check"
- return 1
- fi
-
- for f in check_installed provides check_depends depend; do
- [[ $( type -t ${MODULE}_${f} ) == function ]] && continue
- eerror "${MODULE} does not support the required function ${f}"
- return 1
- done
-
- # Wrap our before/after/need/use functions
- ${MODULE}_depend
-
- return 0
- }
-
- # bool modules_load_auto()
- #
- # Load and check each module for sanity
- # If the module is not installed, the functions are to be removed
- modules_load_auto() {
- local e f i j beforefuncs afterfuncs diffs unload
-
- # Populate the MODULES array
- MODULES=( $( find ${MODULES_DIR}/ -maxdepth 1 -type f ! -name ".*" | sort ) )
-
- # Each of these sources into the global namespace, so it's
- # important that module functions and variables are prefixed with
- # the module name, for example iproute2_
-
- beforefuncs="$( typeset -F )"
- j=${#MODULES[@]}
- loaded_interface=false
- for (( i=0; i<j; i++ )); do
-
- unload=false
- module_load_minimum ${MODULES[i]} || unload=true
- MODULES[i]=${MODULES[i]##*/}
-
- ! ${unload} && ${MODULES[i]}_check_installed false || unload=true
-
- if [[ ${MODULES[i]} == interface ]]; then
- eerror "interface is a reserved name - cannot load a module called interface"
- return 1
- fi
-
- afterfuncs="$( typeset -F )"
- if ${unload} ; then
- unset MODULES[i]
- unsetfuncs="${unsetfuncs} $( diff -U0 <( echo "${beforefuncs}" ) <( echo "${afterfuncs}" ) 2>/dev/null \
- | awk 'BEGIN { ORS = " "; } /+declare -f/ { print $3; }' )"
- fi
- beforefuncs="${afterfuncs}"
-
- done
- MODULES=( "${MODULES[@]}" )
-
- return 0
- }
-
-
- # bool modules_check_installed(void)
- #
- # Ensure that all modules have the required modules loaded
- # This enables us to remove modules from the MODULES array
- # Whilst other modules can still explicitly call them
- # One example of this is essidnet which configures network
- # settings for the specific ESSID connected to as the user
- # may be using a daemon to configure wireless instead of our
- # iwconfig module
- modules_check_installed() {
- local i j missingdeps nmods=${#MODULES[@]}
-
- for (( i=0; i<nmods; i++ )); do
- [[ $( type -t ${MODULES[i]}_instlled ) != function ]] && continue
- for j in $( ${MODULES[i]}_instlled ); do
- missingdeps=true
- if [[ $( type -t ${j}_check_installed ) == function ]]; then
- ${j}_check_installed && missingdeps=false
- fi
- ${missingdeps} && unset MODULES[i] && unset PROVIDES[i] && break
- done
- done
-
- MODULES=( "${MODULES[@]}" )
- PROVIDES=( "${PROVIDES[@]}" )
- }
-
- # bool modules_check_user(void)
- modules_check_user() {
- local -a umods
- local i j k l npref nmods=${#MODULES[@]}
-
- # Has the interface got any specific modules?
- eval umods=( \"\$\{modules_${iface}\[@\]\}\" )
-
- # Global setting follows interface-specific setting
- umods=( "${umods[@]}" "${modules[@]}" )
-
- # Add our preferred modules
- npref=3
- umods=( "${umods[@]}" "ifconfig" "dhcpcd" "iwconfig" )
-
- # First we strip any modules that conflict from user settings
- # So if the user specifies pump then we don't use dhcpcd
- for (( i=0; i<${#umods[@]}; i++ )); do
- # Some users will inevitably put "dhcp" in their modules
- # list. To keep users from screwing up their system this
- # way, ignore this setting so that the default dhcp
- # module will be used.
- [[ ${umods[i]} == dhcp ]] && continue
-
- # We remove any modules we explicitly don't want
- if [[ ${umods[i]} == !* ]]; then
- for (( j=0; j<nmods; j++ )); do
- [[ -z ${MODULES[j]} ]] && continue
- if [[ ${umods[i]:1} == ${MODULES[j]} || ${umods[i]:1} == ${PROVIDES[j]} ]]; then
- # We may need to setup a class wrapper for it even though
- # we don't use it directly
- ${MODULES[j]}_check_installed && module_class_wrap ${MODULES[j]}
- unset MODULES[j]
- unset PROVIDES[j]
- break
- fi
- done
- continue
- fi
-
- if [[ $( type -t ${umods[i]}_provides ) != function ]]; then
- # If the module is one of our preferred modules, then
- # ignore this error; whatever is available will be
- # used instead.
- (( i < ${#umods[@]} - npref )) || continue
- eerror "${umods[i]} is not a valid module (missing provides)"
- return 1
- fi
-
- # Ensure that the user specified module has its package installed
- if (( i < ${#umods[@]} - npref )); then
- # $1==true causes check_installed to report its own errors
- ${umods[i]}_check_installed true || return 1
- else
- # If this happens on a preferred modules, ignore it;
- # whatever is available will be used instead.
- ${umods[i]}_check_installed false || continue
- fi
-
- mod=$( ${umods[i]}_provides )
- for (( j=0; j<nmods; j++ )); do
- [[ -z ${MODULES[j]} ]] && continue
- if [[ ${PROVIDES[j]} == ${mod} && ${umods[i]} != ${MODULES[j]} ]]; then
- # We don't have a match - now ensure that we still provide an alternative.
- # This is to handle our preferred modules.
- for (( l=0; l<nmods; l++ )); do
- [[ ${l} -eq ${j} || -z ${MODULES[l]} ]] && continue
- if [[ ${PROVIDES[l]} == ${mod} ]]; then
- unset MODULES[j]
- unset PROVIDES[j]
- break
- fi
- done
- fi
- done
- done
-
- # Then we strip conflicting modules.
- # We only need to do this for 3rd party modules that conflict with
- # our own modules and the preferred list AND the user modules
- # list doesn't specify a preference.
- for (( i=0; i<nmods-1; i++ )); do
- [[ -z ${MODULES[i]} ]] && continue
- for (( j=i+1; j<nmods; j++)); do
- [[ -z ${MODULES[j]} ]] && continue
- [[ ${PROVIDES[i]} == ${PROVIDES[j]} ]] && unset MODULES[j] && unset PROVIDES[j]
- done
- done
-
- MODULES=( "${MODULES[@]}" )
- PROVIDES=( "${PROVIDES[@]}" )
- return 0
- }
-
- # void modules_sort(void)
-
- modules_sort() {
- local -a modnums sort_history modafter modbefore
- local i j k p changed_something nmods=${#MODULES[@]}
-
- # Sort our modules
- # We do this by assigning numbers to each module
- # We also assign modbefore and modafter so we don't
- # shell out as much because it's expensive on CPU.
- modnums=()
- for (( i=0; i<nmods; i++ )); do
- modnums[i]=${i}
- [[ $( type -t ${MODULES[i]}_after ) == function ]] && modafter[i]=$( ${MODULES[i]}_after )
- [[ $( type -t ${MODULES[i]}_before ) == function ]] && modbefore[i]=$( ${MODULES[i]}_before )
- done
-
- # Then we swap numbers based on and after/before flags
- # until we don't swap anymore. The sort_history array prevents
- # the possibility of an infinite loop
- sort_history[0]="${modnums[*]}"
- for (( k=1; 1; k++ )); do
- changed_something=false
- for (( i=0; i<nmods; i++ )); do
- for p in ${modafter[i]}; do
- for (( j=0; j<nmods; j++ )); do
- [[ ${p} != ${MODULES[j]} && ${p} != ${PROVIDES[j]} ]] && continue
- if [[ ${modnums[i]} -lt ${modnums[j]} ]]; then
- tmp=${modnums[i]}
- modnums[i]=${modnums[j]}
- modnums[j]=${tmp}
- changed_something=true
- fi
- done
- done
- for p in ${modbefore[i]}; do
- for (( j=0; j<nmods; j++ )); do
- [[ ${p} != ${MODULES[j]} && ${p} != ${PROVIDES[j]} ]] && continue
- if [[ ${modnums[i]} -gt ${modnums[j]} ]]; then
- tmp=${modnums[i]}
- modnums[i]=${modnums[j]}
- modnums[j]=${tmp}
- changed_something=true
- fi
- done
- done
- done
- ${changed_something} || break
-
- # Make sure we aren't repeating a previous state
- # First time through, k=1, k/2=0
- sort_history[k]="${modnums[*]}"
- if [[ ${sort_history[k]} == ${sort_history[k/2]} ]]; then
- eerror "Detected an infinite loop sorting modules; blundering ahead"
- break
- fi
- done
-
- # Finally we sort our modules in number order
- um=""
- for (( i=0; i<nmods; i++ )); do
- um="${um}${modnums[i]} ${MODULES[i]} ${PROVIDES[i]}\n"
- done
-
- p=( $( echo -e "${um}" | sort -n | awk '{print $2,$3}' ) )
- MODULES=()
- PROVIDES=()
- j=0
- for (( i=0; i<${#p[@]}; i+=2 )); do
- MODULES[j]=${p[i]}
- PROVIDES[j]=${p[i+1]}
- (( j++ ))
- done
- }
-
- # bool modules_check_depends(bool showprovides)
- modules_check_depends() {
- local showprovides=${1:-false} nmods=${#MODULES[@]} i j needmod
- local missingdeps p interface=false
-
- for (( i=0; i<nmods; i++ )); do
- if [[ $( type -t ${MODULES[i]}_need ) == function ]]; then
- for needmod in $( ${MODULES[i]}_need ); do
- missingdeps=true
- for (( j=0; j<nmods; j++ )); do
- if [[ ${needmod} == ${MODULES[j]} || ${needmod} == ${PROVIDES[j]} ]]; then
- missingdeps=false
- break
- fi
- done
- if ${missingdeps} ; then
- eerror "${MODULES[i]} needs ${needmod} (dependency failure)"
- return 1
- fi
- done
- fi
-
- ${MODULES[i]}_check_depends || return 1
- [[ ${PROVIDES[i]} == interface ]] && interface=true
-
- if ${showprovides} ; then
- [[ ${PROVIDES[i]} != ${MODULES[i]} ]] && veinfo "${MODULES[i]} provides ${PROVIDES[i]}"
- fi
- done
-
- if ! ${interface} ; then
- eerror "no interface module has been loaded"
- return 1
- fi
-
- return 0
- }
-
- # bool modules_load(char *iface, bool starting)
- #
- # Loads the defined handler and modules for the interface
- # Returns 0 on success, otherwise 1
- modules_load() {
- local iface=${1} starting=${2:-true} mod p=false i j unsetfuncs
- local -a x
- local RC_INDENTATION=${RC_INDENTATION} # so it will reset after function
- local -a PROVIDES
-
- if [[ ${iface} == lo ]]; then
- # We force lo to only use these modules for a major speed boost
- modules_force=( "iproute2" "ifconfig" )
- else
- eval x=( \"\$\{modules_force_${iface}\[@\]\}\" )
- [[ -n ${x} ]] && modules_force=( "${x[@]}" )
- if [[ -n ${modules_force} ]]; then
- ewarn "WARNING: You are forcing modules!"
- ewarn "Do not complain or file bugs if things start breaking"
- report=true
- fi
- veinfo "Loading networking modules for ${iface}"
- fi
- eindent
-
- if [[ -z ${modules_force} ]]; then
- modules_load_auto || return 1
- else
- j=${#modules_force[@]}
- for (( i=0; i<j; i++ )); do
- module_load_minimum "${MODULES_DIR}/${modules_force[i]}" || return 1
- ${modules_force[i]}_check_installed || unset modules_force[i]
- done
- MODULES=( "${modules_force[@]}" )
- fi
-
- # We now buffer the _provides functions for a big speed boost
- j=${#MODULES[@]}
- for (( i=0; i<j; i++ )); do
- PROVIDES[i]=$( ${MODULES[i]}_provides )
- done
-
- if [[ -z ${modules_force[@]} ]]; then
- if ${starting}; then
- modules_check_user || return 1
- fi
-
- # We unset unloaded module functions here as so we can error
- # with a message informing the user to emerge the correct
- # package if it's in their modules
- [[ -n ${unsetfuncs} ]] && unset ${unsetfuncs}
-
- modules_sort
- fi
-
- # Setup class wrappers: interface_up -> iproute2_up, for example
- j=${#MODULES[@]}
- for (( i=0; i<j; i++ )); do
- module_class_wrap ${MODULES[i]} ${PROVIDES[i]}
- done
-
- modules_check_installed || return 1
-
- [[ ${iface} != lo ]] && veinfo "modules: ${MODULES[@]}"
- eindent
-
- [[ ${iface} != lo && ${starting} == true ]] && p=true
- modules_check_depends ${p} || return 1
- return 0
- }
-
- # bool iface_start(char *interface)
- #
- # iface_start is called from start. It's expected to start the base
- # interface (for example "eth0"), aliases (for example "eth0:1") and to start
- # VLAN interfaces (for example eth0.0, eth0.1). VLAN setup is accomplished by
- # calling itself recursively.
- iface_start() {
- local iface=${1} mod config_counter=-1 x warn=false config_worked=false
- local RC_INDENTATION=${RC_INDENTATION} # so it will reset after function
- local -a config fallback fallback_route conf
- local ifvar=$( interface_variable ${iface} )
-
- # pre Start any modules with
- for mod in ${MODULES[@]}; do
- if [[ $( type -t ${mod}_pre_start ) == function ]]; then
- ${mod}_pre_start ${iface} || { eend 1; return 1; }
- fi
- done
-
- # New style config - one variable fits all
- eval config=( \"\$\{config_${ifvar}\[@\]\}\" )
- eval fallback=( \"\$\{fallback_${ifvar}\[@\]\}\" )
- eval fallback_route=( \"\$\{fallback_route_${ifvar}\[@\]\}\" )
-
- # We must support old configs
- if [[ -z ${config} ]]; then
- interface_get_old_config ${iface} || return 1
- fi
-
- # Handle "noop" correctly
- if [[ ${config[0]} == "noop" ]]; then
- if interface_is_up ${iface} true ; then
- einfo "Keeping current configuration for ${iface}"
- eend 0
- return 0
- fi
-
- # Remove noop from the config var
- config=( "${config[@]:1}" )
- fi
-
- # Provide a default of DHCP if no configuration is set
- if [[ -z ${config} ]]; then
- if [[ $( type -t dhcp_start ) == function ]]; then
- config=( "dhcp" )
- warn=true
- else
- eerror "Cannot default to dhcp as there is no dhcp module loaded"
- eerror "No configuration for ${iface}"
- return 1
- fi
- fi
-
- einfo "Bringing up ${iface}"
- eindent
- for (( config_counter=0; config_counter<${#config[@]}; config_counter++ )); do
- # Handle null and noop correctly
- if [[ ${config[config_counter]} == "null" \
- || ${config[config_counter]} == "noop" ]]; then
- eend 0
- config_worked=true
- continue
- fi
-
- if ${warn}; then
- ewarn "Configuration not set for ${iface} - assuming dhcp"
- warn=false
- fi
-
- # We convert it to an array - this has the added
- # bonus of trimming spaces!
- conf=( ${config[config_counter]} )
- einfo "${conf[0]}"
-
- # Do we have a function for our config?
- if [[ $( type -t ${conf[0]}_start ) == function ]]; then
- # Check that the module is valid
- x=false
- for mod in ${MODULES[@]}; do
- if [[ $( ${mod}_provides ) == ${conf[0]} ]]; then
- x=true
- break
- fi
- done
-
- if ! ${x}; then
- [[ $( type -t ${conf[0]}_check_installed == function ) ]] && ${conf[0]}_check_installed true
- eerror "No loaded modules provide \"${conf[0]}\" (${conf[0]}_start)"
- else
- eindent
- ${conf[0]}_start ${iface} ; x=$?
- eoutdent
- [[ ${x} == 0 ]] && config_worked=true && continue
- fi
- # We need to test to see if it's an IP address or a function
- # We do this by testing if the 1st character is a digit
- elif [[ ${conf[0]:0:1} == [[:digit:]] || ${conf[0]} == *:* ]]; then
- x=0
- # if [[ $(type -t address_exists ) == function ]]; then
- # if address_exists ${iface} ${conf[0]} ; then
- # eerror "${conf[0]%%/*} already taken on ${iface}"
- # x=1
- # fi
- # fi
- [[ ${x} == 0 ]] && interface_add_address ${iface} ${conf[@]} ; x=$?
- eend ${x} && config_worked=true && continue
- else
- eerror "No loaded modules provide \"${conf[0]}\" (${conf[0]}_start)"
- fi
-
- if [[ -n ${fallback[config_counter]} ]]; then
- einfo "Trying fallback configuration"
- config[config_counter]=${fallback[config_counter]}
- fallback[config_counter]=''
-
- # Do we have a fallback route?
- if [[ -n ${fallback_route[config_counter]} ]]; then
- eval "routes_${ifvar}=( "\"\$\{fallback_route\[${config_counter}\]\[@\]\}\"" )"
- fallback_route[config_counter]=''
- fi
-
- (( config_counter-- )) # since the loop will increment it
- continue
- fi
- done
- eoutdent
-
- # We return failure if no configuration parameters worked
- ${config_worked} || return 1
-
- # Start any modules with _post_start
- for mod in ${MODULES[@]}; do
- if [[ function == $( type -t ${mod}_post_start ) ]]; then
- ${mod}_post_start ${iface} || return 1
- fi
- done
-
- return 0
- }
-
- # bool iface_stop(char *interface)
- #
- # iface_stop: bring down an interface. Don't trust information in
- # /etc/conf.d/net since the configuration might have changed since
- # iface_start ran. Instead query for current configuration and bring
- # down the interface.
- #
- # However, we are currently reliant on handler and modules specified
- # in /etc/conf.d/net
- iface_stop() {
- local iface=${1} i aliases need_begin=false mod
- local RC_INDENTATION=${RC_INDENTATION} # so it will reset after function
-
- # pre Stop any modules
- for mod in ${MODULES[@]}; do
- [[ $( type -t ${mod}_pre_stop ) == function ]] && ${mod}_pre_stop ${iface}
- done
-
- einfo "Bringing down ${iface}"
- eindent
-
- # Collect list of aliases for this interface.
- # List will be in reverse order.
- aliases=$( interface_get_aliases_rev ${iface} )
-
- # Stop aliases before primary interface.
- # Note this must be done in reverse order, since ifconfig eth0:1
- # will remove eth0:2, etc. It might be sufficient to simply remove
- # the base interface but we're being safe here.
- for i in ${aliases} ${iface}; do
- # Stop all our modules
- for mod in ${MODULES[@]}; do
- [[ $( type -t ${mod}_stop ) == function ]] && ${mod}_stop ${i}
- done
-
- # A module may have removed the interface
- interface_exists ${iface} || { eend 0; continue; }
-
- # Delete all the addresses for this alias
- interface_del_addresses ${i}
-
- # Do final shut down of this alias
- ebegin "Shutting down ${i}"
- interface_iface_stop ${i}
- eend $?
- done
-
- # post Stop any modules
- for mod in ${MODULES[@]}; do
- # We have already taken down the interface, so no need to error
- [[ $( type -t ${mod}_post_stop ) == function ]] && ${mod}_post_stop ${iface}
- done
-
- return 0
- }
-
- # bool run_start(char *iface)
- #
- # Brings up ${IFACE}. Calls preup, iface_start, then postup.
- # Returns 0 (success) unless preup or iface_start returns 1 (failure).
- # Ignores the return value from postup.
- # We cannot check that the device exists ourselves as modules like
- # tuntap make create it.
- run_start() {
- local iface=${1} ifvar x
-
- if [[ ${iface} == lo ]]; then
- ebegin "Bringing up ${iface}"
- interface_loopback_create
- eend $?
- return $?
- fi
-
- # We may not have a loaded module for ${iface}
- # Some users may have "alias natsemi eth0" in /etc/modules.d/foo
- # so we can work with this
- # However, if they do the same with eth1 and try to start it
- # but eth0 has not been loaded then the module gets loaded as
- # eth0.
- # Not much we can do about this :(
- # Also, we cannot error here as some modules - such as bridge
- # create interfaces
- if ! interface_exists ${iface} ; then
- /sbin/modprobe ${iface} &>/dev/null
- fi
-
- # Setup variables for pre/post to use
- ifvar=$( interface_variable ${iface} )
- local IFACE=${iface} IFVAR=${ifvar}
-
- # Call user-defined preup function if it exists
- if [[ $( type -t preup ) == function ]]; then
- einfo "Running preup function"
- eindent
- preup ${iface} ; x=$?
- eoutdent
- if [[ ${x} != 0 ]]; then
- eerror "preup ${iface} failed"
- return 1
- fi
- fi
-
- # Don't let preup modify us
- iface=${1}
- local IFACE=${iface} IFVAR=${ifvar} config
-
- # If config is set to noop and the interface is up with an address
- # then we don't start it
- eval config=( \"\$\{config_${ifvar}\[@\]\}\" )
- if [[ ${config[0]} == "noop" ]] && interface_is_up ${iface} true ; then
- einfo "Keeping current configuration for ${iface}"
- eend 0
- else
- # Remove noop from the config var
- [[ ${config[0]} == "noop" ]] && eval "config_${ifvar}=( "\"\$\{config\[@\]:1\}\"" )"
-
- # There may be existing ip address info - so we strip it
- interface_del_addresses ${iface}
-
- # Start the interface
- if ! iface_start ${iface} ; then
- interface_exists ${iface} && interface_down ${iface}
- eend 1
- return 1
- fi
- fi
-
- # Call user-defined postup function if it exists
- if [[ $( type -t postup ) == function ]]; then
- einfo "Running postup function"
- eindent
- postup ${iface}
- eoutdent
- fi
-
- return 0
- }
-
- # bool run_stop(char *iface) {
- #
- # Brings down ${iface}. If predown call returns non-zero, then
- # stop returns non-zero to indicate failure bringing down device.
- # In all other cases stop returns 0 to indicate success.
- run_stop() {
- local iface=${1} ifvar x
-
- # Don't run any special shutdown functions for lo
- if [[ ${iface} == lo ]]; then
- ebegin "Shutting down ${iface}"
- interface_iface_stop ${iface}
- eend $?
- return 0
- fi
-
- # Setup variables for pre/post to use
- ifvar=$( interface_variable ${iface} )
- local IFACE=${iface} IFVAR=${ifvar}
-
- # Call user-defined predown function if it exists
- if [[ $( type -t predown ) == function ]]; then
- einfo "Running predown function"
- eindent
- predown ${iface} ; x=$?
- eoutdent
- if [[ ${x} != 0 ]]; then
- eend 1 "predown ${iface} failed"
- return 1
- fi
- elif is_net_fs /; then
- eerror "root filesystem is network mounted -- can't stop ${iface}"
- return 1
- fi
-
- # Don't let predown modify us
- iface=${1}
- local IFACE=${iface} IFVAR=${ifvar}
-
- iface_stop ${iface} || return 1 # always succeeds, btw
-
- # Call user-defined postdown function if it exists
- if [[ $( type -t postdown ) == function ]]; then
- einfo "Running postdown function"
- eindent
- postdown ${iface}
- eoutdent
- fi
-
- return 0
- }
-
- # bool run(char *iface, char *cmd)
- #
- # Main start/stop entry point
- # We load modules here and remove any functions that they
- # added as we may be called inside the same shell scope for another interface
- run() {
- local iface=${1} cmd=${2} r=1 RC_INDENTATION=${RC_INDENTATION} # so it will reset after function
- local before starting=true
- local -a MODULES mods
-
- # We need to override the exit function as runscript.sh now checks
- # for it. We need it so we can mark the service as inactive ourselves.
- unset -f exit
-
- eindent
-
- unset_functions=${unset_functions:-false}
- ${unset_functions} && before="$( typeset -F )"
- [[ ${cmd} == "stop" ]] && starting=false
- if modules_load ${iface} ${starting} ; then
- if [[ ${cmd} == "stop" ]]; then
- # Reverse the module list for stopping
- mods=( "${MODULES[@]}" )
- for ((i = 0; i < ${#mods[@]}; i++)); do
- MODULES[i]=${mods[((${#mods[@]} - i - 1))]}
- done
-
- run_stop ${iface} && r=0
- else
- run_start ${iface} && r=0
- fi
- fi
-
- # We need to remove added functions before we quit as other init
- # scripts may be launching afterwards
- ${unset_functions} && \
- unset $( diff -U0 <( echo "${before}" ) <( echo "$( typeset -F )" ) 2>/dev/null \
- | awk 'BEGIN { ORS = " "; } /+declare -f/ { print $3; }' ) 2>/dev/null
-
- return ${r}
- }
-
- # bool start(void)
- #
- # Start entry point so that we only have one function
- # which localises variables and unsets functions
- start() {
- einfo "Starting ${IFACE}"
- run ${IFACE} start
- return $?
- }
-
- # bool stop(void)
- #
- # Stop entry point so that we only have one function
- # which localises variables and unsets functions
- stop() {
- einfo "Stopping ${IFACE}"
- run ${IFACE} stop
- return $?
- }
-
- # bool restart(void)
- #
- # Restart entry point
- # We do this so as we only have to remove functions when stopping
- restart() {
- local unset_functions=true
- service_started "${myservice}" && svc_stop
- unset_functions=false
- svc_start
- return $?
- }
-
- # vim:ts=4
-